package org.ehe.business.bom.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.ehe.business.bom.domain.BomStructure;
import org.ehe.business.bom.mapper.BomStructureMapper;
import org.ehe.business.bom.service.BomStructureService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * @author :zhangnn
 * @className :BomStructureServiceImpl
 * @description: TODO
 * @date 2025-07-30 14:01:31
 */
@Slf4j
@Service
public class BomStructureServiceImpl extends ServiceImpl<BomStructureMapper, BomStructure> implements BomStructureService {

    /**
     * 获取BOM版本的完整结构树
     */
    public List<BomStructure> getBomStructureTree(Long bomVersionId) {
        log.info("获取BOM结构树: bomVersionId={}", bomVersionId);

        QueryWrapper<BomStructure> wrapper = new QueryWrapper<>();
        wrapper.eq("bom_version_id", bomVersionId)
            .orderBy(true, true, "level_no", "seq_no");

        List<BomStructure> allStructures = this.list(wrapper);

        // 构建树形结构
        return buildTree(allStructures);
    }

    /**
     * 构建树形结构
     */
    private List<BomStructure> buildTree(List<BomStructure> allStructures) {
        Map<Long, List<BomStructure>> parentChildMap = new HashMap<>();
        List<BomStructure> rootNodes = new ArrayList<>();

        // 按父级ID分组
        for (BomStructure structure : allStructures) {
            Long parentId = structure.getParentItemId();
            if (parentId == null) {
                rootNodes.add(structure);
            } else {
                parentChildMap.computeIfAbsent(parentId, k -> new ArrayList<>()).add(structure);
            }
        }

        // 设置子节点（这里简化处理，实际项目中可能需要在实体类中添加children字段）
        return rootNodes;
    }

    /**
     * 添加BOM结构项
     */
    @Transactional
    public void addBomStructureItem(BomStructure bomStructure) {
        log.info("添加BOM结构项: itemCode={}, itemName={}",
            bomStructure.getItemCode(), bomStructure.getItemName());

        // 验证必填字段
        bomStructure.setId(null);
        validateBomStructure(bomStructure);

        // 设置层级编号
        if (bomStructure.getLevelNo() == null) {
            bomStructure.setLevelNo(calculateLevelNo(bomStructure.getParentItemId(), bomStructure.getBomVersionId()));
        }

        // 设置序号
        if (bomStructure.getSeqNo() == null) {
            bomStructure.setSeqNo(getNextSeqNo(bomStructure.getBomVersionId(), bomStructure.getParentItemId()));
        }

        // 计算总价
        calculateTotalPrice(bomStructure);

        bomStructure.setCreateTime(new Date());
        if(null != bomStructure.getId()){
            this.updateBomStructureItem(bomStructure);
        } else {
            this.save(bomStructure);
        }

        log.info("BOM结构项添加成功: id={}", bomStructure.getId());
        //return bomStructure;
    }

    /**
     * 更新BOM结构项
     */
    @Transactional
    public void updateBomStructureItem(BomStructure bomStructure) {
        log.info("更新BOM结构项: id={}", bomStructure.getId());

        validateBomStructure(bomStructure);
        calculateTotalPrice(bomStructure);

        bomStructure.setUpdateTime(new Date());
        this.updateById(bomStructure);

        log.info("BOM结构项更新成功: id={}", bomStructure.getId());
    }

    @Override
    public void clearVersionStructures(Long bomVersionId) {
        log.info("清除版本结构: bomVersionId={}", bomVersionId);

        LambdaQueryWrapper<BomStructure> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(BomStructure::getBomVersionId, bomVersionId);

        this.remove(wrapper);
    }

    /**
     * 删除BOM结构项（包括子项）
     */
    @Transactional
    public void deleteBomStructureItem(Long structureId) {
        log.info("删除BOM结构项: structureId={}", structureId);

        BomStructure structure = this.getById(structureId);
        if (structure == null) {
            throw new RuntimeException("BOM结构项不存在");
        }

        // 递归删除所有子项
        deleteChildrenRecursively(structureId);

        // 删除当前项
        this.removeById(structureId);

        log.info("BOM结构项删除成功: structureId={}", structureId);
    }

    /**
     * 递归删除子项
     */
    private void deleteChildrenRecursively(Long parentItemId) {
        QueryWrapper<BomStructure> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_item_id", parentItemId);

        List<BomStructure> children = this.list(wrapper);
        for (BomStructure child : children) {
            deleteChildrenRecursively(child.getId());
            this.removeById(child.getId());
        }
    }

    /**
     * 复制BOM结构到新版本
     */
    @Transactional
    public void copyBomStructure(Long sourceVersionId, Long targetVersionId) {
        log.info("复制BOM结构: sourceVersionId={}, targetVersionId={}", sourceVersionId, targetVersionId);

        QueryWrapper<BomStructure> wrapper = new QueryWrapper<>();
        wrapper.eq("bom_version_id", sourceVersionId);

        List<BomStructure> sourceStructures = this.list(wrapper);
        Map<Long, Long> idMapping = new HashMap<>(); // 旧ID到新ID的映射

        // 按层级排序，确保父级先创建
        sourceStructures.sort(Comparator.comparing(BomStructure::getLevelNo)
            .thenComparing(BomStructure::getSeqNo));

        for (BomStructure source : sourceStructures) {
            BomStructure target = new BomStructure();

            // 复制所有字段
            copyBomStructureFields(source, target);

            // 设置新的版本ID
            target.setBomVersionId(targetVersionId);

            // 处理父级关系映射
            if (source.getParentItemId() != null) {
                target.setParentItemId(idMapping.get(source.getParentItemId()));
            }

            target.setCreateTime(new Date());
            this.save(target);

            // 保存ID映射关系
            idMapping.put(source.getId(), target.getId());
        }

        log.info("BOM结构复制成功，共复制{}条记录", sourceStructures.size());
    }

    /**
     * 复制BOM结构字段
     */
    private void copyBomStructureFields(BomStructure source, BomStructure target) {
        target.setItemId(source.getItemId());
        target.setItemCode(source.getItemCode());
        target.setItemName(source.getItemName());
        target.setItemType(source.getItemType());
        target.setSpecification(source.getSpecification());
        target.setUnit(source.getUnit());
        target.setQuantity(source.getQuantity());
        target.setScrapRate(source.getScrapRate());
        target.setLevelNo(source.getLevelNo());
        target.setSeqNo(source.getSeqNo());
        target.setIsKeyItem(source.getIsKeyItem());
        target.setIsOptional(source.getIsOptional());
        target.setSubstituteGroup(source.getSubstituteGroup());
        target.setSupplierId(source.getSupplierId());
        target.setSupplierName(source.getSupplierName());
        target.setUnitPrice(source.getUnitPrice());
        target.setTotalPrice(source.getTotalPrice());
        target.setLeadTime(source.getLeadTime());
        target.setRemark(source.getRemark());
    }

    /**
     * 验证BOM结构数据
     */
    private void validateBomStructure(BomStructure bomStructure) {
        if (bomStructure.getBomVersionId() == null) {
            throw new RuntimeException("BOM版本ID不能为空");
        }

        if (bomStructure.getItemId() == null) {
            throw new RuntimeException("物料ID不能为空");
        }

        if (bomStructure.getQuantity() == null || bomStructure.getQuantity().compareTo(BigDecimal.ZERO) <= 0) {
            throw new RuntimeException("用量必须大于0");
        }

        if (bomStructure.getScrapRate() != null &&
            (bomStructure.getScrapRate().compareTo(BigDecimal.ZERO) < 0 ||
                bomStructure.getScrapRate().compareTo(new BigDecimal("100")) > 0)) {
            throw new RuntimeException("损耗率必须在0-100之间");
        }
    }

    /**
     * 计算层级编号
     */
    private Integer calculateLevelNo(Long parentItemId, Long bomVersionId) {
        if (parentItemId == null) {
            return 1; // 顶级
        }

        QueryWrapper<BomStructure> wrapper = new QueryWrapper<>();
        wrapper.eq("bom_version_id", bomVersionId)
            .eq("id", parentItemId);

        BomStructure parent = this.getOne(wrapper);
        if (parent != null) {
            return parent.getLevelNo() + 1;
        }

        return 1;
    }

    /**
     * 获取下一个序号
     */
    private Integer getNextSeqNo(Long bomVersionId, Long parentItemId) {
        QueryWrapper<BomStructure> wrapper = new QueryWrapper<>();
        wrapper.eq("bom_version_id", bomVersionId);

        if (parentItemId != null) {
            wrapper.eq("parent_item_id", parentItemId);
        } else {
            wrapper.isNull("parent_item_id");
        }

        wrapper.orderByDesc("seq_no").last("LIMIT 1");

        BomStructure lastItem = this.getOne(wrapper);
        if (lastItem != null && lastItem.getSeqNo() != null) {
            return lastItem.getSeqNo() + 1;
        }

        return 1;
    }

    /**
     * 计算总价
     */
    private void calculateTotalPrice(BomStructure bomStructure) {
        if (bomStructure.getQuantity() != null && bomStructure.getUnitPrice() != null) {
            BigDecimal scrapRate = bomStructure.getScrapRate() != null ? bomStructure.getScrapRate() : BigDecimal.ZERO;
            BigDecimal actualQuantity = bomStructure.getQuantity().multiply(
                BigDecimal.ONE.add(scrapRate.divide(new BigDecimal("100")))
            );
            bomStructure.setTotalPrice(actualQuantity.multiply(bomStructure.getUnitPrice()));
        }
    }

    /**
     * 获取BOM物料清单（平铺）
     */
    public List<BomStructure> getBomMaterialList(Long bomVersionId) {
        QueryWrapper<BomStructure> wrapper = new QueryWrapper<>();
        wrapper.eq("bom_version_id", bomVersionId)
            .orderBy(true, true, "level_no", "seq_no");
        return this.list(wrapper);
    }

    /**
     * 获取指定层级的BOM结构
     */
    public List<BomStructure> getBomStructureByLevel(Long bomVersionId, Integer levelNo) {
        QueryWrapper<BomStructure> wrapper = new QueryWrapper<>();
        wrapper.eq("bom_version_id", bomVersionId)
            .eq("level_no", levelNo)
            .orderBy(true, true, "seq_no");
        return this.list(wrapper);
    }

    /**
     * 获取顶级BOM结构项
     */
    public List<BomStructure> getTopLevelItems(Long bomVersionId) {
        QueryWrapper<BomStructure> wrapper = new QueryWrapper<>();
        wrapper.eq("bom_version_id", bomVersionId)
            .isNull("parent_item_id")
            .orderBy(true, true, "seq_no");
        return this.list(wrapper);
    }

    /**
     * 获取子级BOM结构项
     */
    public List<BomStructure> getChildItems(Long parentItemId) {
        QueryWrapper<BomStructure> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_item_id", parentItemId)
            .orderBy(true, true, "seq_no");
        return this.list(wrapper);
    }

    /**
     * 计算BOM总成本
     */
    public BigDecimal calculateBomTotalCost(Long bomVersionId) {
        QueryWrapper<BomStructure> wrapper = new QueryWrapper<>();
        wrapper.eq("bom_version_id", bomVersionId);

        List<BomStructure> structures = this.list(wrapper);

        return structures.stream()
            .filter(s -> s.getTotalPrice() != null)
            .map(BomStructure::getTotalPrice)
            .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 查找关键物料
     */
    public List<BomStructure> getKeyItems(Long bomVersionId) {
        QueryWrapper<BomStructure> wrapper = new QueryWrapper<>();
        wrapper.eq("bom_version_id", bomVersionId)
            .eq("is_key_item", 1)
            .orderBy(true, true, "level_no", "seq_no");
        return this.list(wrapper);
    }

    /**
     * 查找可选物料
     */
    public List<BomStructure> getOptionalItems(Long bomVersionId) {
        QueryWrapper<BomStructure> wrapper = new QueryWrapper<>();
        wrapper.eq("bom_version_id", bomVersionId)
            .eq("is_optional", 1)
            .orderBy(true, true, "level_no", "seq_no");
        return this.list(wrapper);
    }

    /**
     * 根据替代组查找物料
     */
    public List<BomStructure> getItemsBySubstituteGroup(Long bomVersionId, String substituteGroup) {
        QueryWrapper<BomStructure> wrapper = new QueryWrapper<>();
        wrapper.eq("bom_version_id", bomVersionId)
            .eq("substitute_group", substituteGroup)
            .orderBy(true, true, "level_no", "seq_no");
        return this.list(wrapper);
    }

    /**
     * 更新物料单价并重新计算总价
     */
    @Transactional
    public void updateItemPrice(Long bomVersionId, Long itemId, BigDecimal newUnitPrice) {
        log.info("更新物料单价: bomVersionId={}, itemId={}, newPrice={}", bomVersionId, itemId, newUnitPrice);

        QueryWrapper<BomStructure> wrapper = new QueryWrapper<>();
        wrapper.eq("bom_version_id", bomVersionId)
            .eq("item_id", itemId);

        List<BomStructure> structures = this.list(wrapper);

        for (BomStructure structure : structures) {
            structure.setUnitPrice(newUnitPrice);
            calculateTotalPrice(structure);
            structure.setUpdateTime(new Date());
            this.updateById(structure);
        }

        log.info("物料单价更新完成，共更新{}条记录", structures.size());
    }

    /**
     * 批量更新供应商信息
     */
    @Transactional
    public void updateSupplierInfo(Long bomVersionId, Long itemId, Long supplierId, String supplierName) {
        log.info("更新供应商信息: bomVersionId={}, itemId={}, supplierId={}", bomVersionId, itemId, supplierId);

        QueryWrapper<BomStructure> wrapper = new QueryWrapper<>();
        wrapper.eq("bom_version_id", bomVersionId)
            .eq("item_id", itemId);

        List<BomStructure> structures = this.list(wrapper);

        for (BomStructure structure : structures) {
            structure.setSupplierId(supplierId);
            structure.setSupplierName(supplierName);
            structure.setUpdateTime(new Date());
            this.updateById(structure);
        }

        log.info("供应商信息更新完成，共更新{}条记录", structures.size());
    }

    /**
     * 检查BOM结构完整性
     */
    public List<String> validateBomStructureIntegrity(Long bomVersionId) {
        List<String> issues = new ArrayList<>();

        QueryWrapper<BomStructure> wrapper = new QueryWrapper<>();
        wrapper.eq("bom_version_id", bomVersionId);
        List<BomStructure> structures = this.list(wrapper);

        for (BomStructure structure : structures) {
            // 检查必填字段
            if (structure.getQuantity() == null || structure.getQuantity().compareTo(BigDecimal.ZERO) <= 0) {
                issues.add("物料[" + structure.getItemCode() + "]用量不能为空或小于等于0");
            }

            if (structure.getUnit() == null || structure.getUnit().trim().isEmpty()) {
                issues.add("物料[" + structure.getItemCode() + "]计量单位不能为空");
            }

            // 检查关键物料是否有供应商
//            if (structure.getIsKeyItem() == 1 && structure.getSupplierId() == null) {
//                issues.add("关键物料[" + structure.getItemCode() + "]必须指定供应商");
//            }

            // 检查单价
//            if (structure.getUnitPrice() == null || structure.getUnitPrice().compareTo(BigDecimal.ZERO) <= 0) {
//                issues.add("物料[" + structure.getItemCode() + "]单价不能为空或小于等于0");
//            }
        }

        return issues;
    }
}
